const types     = require("@babel/types");
// 第三方资源导入
const fs            = require('fs');
const parser        = require("@babel/parser");
const traverse      = require("@babel/traverse").default;
const generator     = require("@babel/generator").default;

encodeFile = './boss_cookie/boss_js.js'
decodeFile = './boss_cookie/res.js'
//将源代码解析为AST
let sourceCode = fs.readFileSync(encodeFile, {encoding: "utf-8"});
let ast    = parser.parse(sourceCode);

console.time("处理完毕，耗时");



const simplifyLiteral = { // 16进制，Unicode常量还原
	NumericLiteral({node}) {
		if (node.extra && /^0[obx]/i.test(node.extra.raw)) {
			node.extra = undefined;
		}
  },
  StringLiteral({node}) 
  {
  	if (node.extra && /\\[ux]/gi.test(node.extra.raw)) {
  		node.extra = undefined;
    }
  },
}



/******************************
var变量声明逗号表达式还原
处理前:
var a = 123,b = 456;
let c  = 789,d = 120;
处理后:
var a = 123;
var b = 456;
let c = 789;
let d = 120;
******************************/
const DeclaratorToDeclaration =
{
	VariableDeclaration(path)
	{
		if (path.parentPath.isForStatement()) // for循环里的变量声明不还原
		{
			return;
		}
		
		let {declarations,kind} = path.node;
		if (declarations.length == 1) // VariableDeclaration 中的Declarator只有一个的时候也不需要还原了
		{
			return;
		}
		let newDeclartionNode = types.VariableDeclaration(kind,[declarations[0]]); // 取出列表declarations的第一个元素，构建一个结点
		path.insertBefore(newDeclartionNode);
		declarations.shift(); // 弹出第一个元素
		path.visit(); //遍历此节点
	},
}

// var逗号表示式定义大量函数，还原
const varDeclarToFuncDeclar =   
{
	VariableDeclarator(path) //  直接遍历VariableDeclarator
	{
		let {id,init} = path.node; // 获取函数名和函数体
		if (!types.isFunctionExpression(init,{id:null})) // 如果不是fun类型直接退出
		{
			return;
		}
		let {params,body} = init; // 获取参数和函数体
		let newNode = types.FunctionDeclaration(id,params,body); // 构建新的函数声明结点，非变量赋值写法
		path.parentPath.replaceWith(newNode);
	},
}

//For，While 还原标准循环
/************
for (a=0;a>10;a++)      
  a()                    ExpressionStatement


for (a=0;a>10;a++){
    a()                  BlockStatement
} 
************/
const standardLoop = // 标准循环还原
{
	"ForStatement|WhileStatement"({node})
	{
		if(types.isExpressionStatement(node.body))  //如果循环体是不带大括号的表达式语句，还原成带大括号的BlockStatement块语句
		{
			node.body = types.BlockStatement([node.body]);
		}
    },
}



//字面量解混淆
console.log("traverse Hex or Unicode String......."); // 修复十六进制和Unicode字符
traverse(ast, simplifyLiteral);




let {code} = generator(ast,opts = {jsescOption:{"minimal":true}});

fs.writeFile(decodeFile, code, (err) => {});